<template>
  <span v-if="props.onlyShow">{{ employeeNames }}</span>
  <span
    v-else
    style="width: 100%"
    @mouseenter="hovering = true"
    @mouseleave="hovering = false"
  >
    <el-popover
      ref="popover"
      width="—"
      popper-class="popover"
      placement="bottom-start"
      :visible-arrow="true"
      :disabled="inputDisabled"
      trigger="click"
    >
      <template #reference>
        <el-input
          v-model="message"
          auto-complete="off"
          :disabled="inputDisabled"
          readonly
        >
          <template #suffix>
            <i
              v-if="showClear"
              class="el-input__icon el-icon-circle-close el-input__clear"
              @click.stop="clearInput"
            ></i>
          </template>
        </el-input>
      </template>
      <el-scrollbar
        wrap-class="popover-scrollbar"
        wrap-style="min-width:350px;min-height:450px;max-height:450px;"
        view-style="height:100%;padding:12px;"
        v-loading="loading"
        element-loading-text="数据加载中..."
        :noresize="false"
      >
        <el-tree
          ref="tree"
          node-key="id"
          :class="['employee-tree', leafSelect ? 'leaf-check' : '']"
          :data="treeData"
          :props="treeProps"
          :default-expanded-keys="treeExpanded"
          :default-checked-keys="selectedData"
          :filter-node-method="filterNode"
          @node-click="nodeClick"
        >
        </el-tree>
      </el-scrollbar>
    </el-popover>
  </span>
</template>

<script setup>
import {ref, watch, onMounted, onUnmounted} from 'vue';
import {useEmployeeStore} from '@/pinia/modules/employee';
import {useDisabled} from 'element-plus';
import api from '@/http/api';
import {emitter} from '@/utils/bus';

const emit = defineEmits(['update:modelValue', 'update:orgIdValue', 'change']);
const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  leafSelect: {
    // 是否只有叶节点可选择
    type: Boolean,
    default: true,
  },
  withOrgId: {
    type: Boolean,
    default: false,
  },
  onlyShow: {
    // 是否仅展示
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  placeholder: {
    type: String,
    default: "",
  },
  showText: Boolean,
});

const tree = ref();
const popover = ref();
const filterText = ref("");
const message = ref("");
const loading = ref(false);
const selectedData = ref([props.modelValue || '0']);
const treeExpanded = ref([]);
const inputDisabled = useDisabled();
const treeData = ref([]);
const treeProps = ref({
  children: "children",
  label: 'text'
});
const hovering = ref(false);
const showClear = ref(false);
const employeeStore = useEmployeeStore();
const employeeNames = ref('');

const clearInput = () => {
  message.value = "";
  changeInput("");
};

const filterNode = (value, data) => {
  if (!value) return true;
  return data.text.indexOf(value) !== -1;
};

const nodeClick = (data, node) => {
  if (data.disable === true) {
    emit("update:modelValue", "");
    return;
  }

  if (!props.leafSelect || (props.leafSelect && node.isLeaf)) {
    if (data.disabled !== undefined && data.disabled === true) {
      return;
    }

    let id = data.id || "";
    changeInput(id || "");
    popover.value.hide()
  }
};

const changeInput = (value) => {
  if (props.withOrgId) {
    emit("update:modelValue", value);
    emit("change", value);
  } else {
    let id;
    let orgId = '';
    if (value.indexOf('@') > 0) {
      let ids = value.split('@');
      orgId = ids[0];
      id = ids[1];
    }
    emit("update:orgIdValue", orgId);
    emit("update:modelValue", id);
    emit("change", id);
  }

  popover.value.hide();
};

const loadEmployee = async() => {
  treeData.value = await employeeStore.getEmployee();
  treeExpanded.value = [treeData.value && treeData.value[0] && treeData.value[0].id];
  calcValue();
};

const calcValue = () => {
  message.value = "";
  if (treeData.value == null || treeData.value.length <= 0) {
    message.value = selectedData.value.join(",");
  } else {
    let employees = findEmployee(treeData.value, selectedData.value).reduce((result, item) => {
      if (!result.some(resultItem => resultItem.data.id === item.data.id)) {
        result.push(item);
      }
      return result;
    }, []);

    for (let i = 0; i < employees.length; i++) {
      if (i > 0) {
        message.value += ",";
      }

      if (props.withOrgId) {
        message.value += employees[i].levelText;
      } else {
        message.value += employees[i].text;
      }
    }
  }
};

const findEmployee = (datas, ids) => {
  let results = [];
  if (datas === undefined || datas == null || ids === undefined || ids == null) {
    return results;
  }

  for (let i = 0; i < datas.length; i++) {
    let id = datas[i].id + "";
    if (props.withOrgId) {
      if (ids.includes(id)) {
        results.push(datas[i]);
      }
    } else {
      if (id.indexOf('@') >= 0) {
        id = id.split('@')[1];
      }
      if (id !== "0" && ids.includes(id)) {
        results.push(datas[i]);
      }
    }

    if (datas[i].children !== undefined && datas[i].children != null) {
      results = results.concat(findEmployee(datas[i].children, ids));
    }
  }

  return results;
};

const queryEmployee = (ids) => {
  if ((ids || '') === '') {
    return;
  }

  api.post('/employee/queryByIds', { ids: ids.split(',') }).then(res => {
    employeeNames.value = res.data || '';
  });
};

watch(() => props.modelValue, (newVal) => {
  message.value = "";
  tree.value && tree.value.setCheckedNodes([]);

  selectedData.value = ((newVal || "") + "").split(",");
  if (selectedData.value.length <= 0) {
    return;
  }

  calcValue();
});

watch(() => filterText.value, (newVal) => {
  tree.value.filter(newVal);
});

onMounted(() => {
  selectedData.value = (props.modelValue || '').split(',');

  if (props.onlyShow) {
    queryEmployee(props.modelValue)
  } else {
    loadEmployee();
    emitter.on('employee.change', () => {
      employeeStore.clearEmployee();
      loadEmployee();
    });
  }
});

onUnmounted(() => {
  emitter.off('employee.change');
});
</script>

<style scoped>
.leaf-check :deep(.is-leaf + .el-checkbox .el-checkbox__inner) {
  display: inline-block;
}
.leaf-check :deep(.el-checkbox .el-checkbox__inner) {
  display: none;
}
.employee-tree {
  overflow: auto;
}
</style>
